package cn.iocoder.yudao.module.measure.events.listener;

import cn.iocoder.yudao.module.measure.dal.dataobject.upload.BusinessDeviceUploadData;
import cn.iocoder.yudao.module.measure.dal.dataobject.warning.BusinessDeviceUploadWarningConfig;
import cn.iocoder.yudao.module.measure.dal.dataobject.warning.BusinessDeviceWarnRecord;
import cn.iocoder.yudao.module.measure.events.BusinessDeviceUploadDataEvent;
import cn.iocoder.yudao.module.measure.service.warning.BusinessDeviceUploadWarningConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
@Slf4j
public class DeviceDataCheckListener implements ApplicationListener<BusinessDeviceUploadDataEvent> {

    @Autowired
    private BusinessDeviceUploadWarningConfigService service;

    @Autowired
    private ApplicationContext applicationContext;

    private void checkWarningType(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        // 先判断事件负载数据的数据类型与报警配置期望的数据类型是否一致，如果不一致直接返回
        String checkType = config.getCheckType();
        String configDataType = config.getDataType();
        // 判断数据是否需要处理
        if(payload.getDataType().equals(configDataType)) {
            switch (checkType) {
                case "OVER_LOW_LIMIT":
                    checkOverLowLimitWarningResult(config,payload);
                    break;
                case "OVER_HIGH_LIMIT":
                    checkOverHighLimitWarningResult(config,payload);
                    break;
                case "OVER_SCOPE_LIMIT":
                    checkOverScopeLimitWarningResult(config,payload);
                    break;
                case "LOW_CHANGE_RATE":
                    checkLowChangeRateWarningResult(config,payload);
                    break;
                case "HIGH_CHANGE_RATE":
                    checkHighChangeRateWarningResult(config,payload);
                    break;
                case "SCOPE_CHANGE_RATE":
                    checkScopeChangeRateWarningResult(config,payload);
                    break;
                default:
                    log.debug("未定义的检查方式：{}",checkType);
            }
        }
    }

    private void checkLowChangeRateWarningResult(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        // 取前指定时间段的数据，计算其均值
    }
    private void checkHighChangeRateWarningResult(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        // 取前指定时间段的数据，计算其均值
    }
    private void checkScopeChangeRateWarningResult(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        // 取前指定时间段的数据，计算其均值
    }

    private void checkOverLowLimitWarningResult(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        String lowLimit = config.getLimitLowValue();
        String dataValue = payload.getDataValue();
        if(Double.compare(Double.parseDouble(dataValue), Double.parseDouble(lowLimit))<0){
            String dataType = payload.getDataType();
            BusinessDeviceWarnRecord event = createBusinessDeviceWarnRecord(config,payload);
            event.setWarningContent(dataType +"越下限报警，限制值为："+lowLimit + "； 实际值为："+dataValue );
            applicationContext.publishEvent(event);
        }
    }

    private void checkOverHighLimitWarningResult(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        String highLimit = config.getLimitHighValue();
        String dataValue = payload.getDataValue();
        if(Double.compare(Double.parseDouble(dataValue), Double.parseDouble(highLimit))>0){
            String dataType = payload.getDataType();
            BusinessDeviceWarnRecord event = createBusinessDeviceWarnRecord(config,payload);
            event.setWarningContent( dataType +"越上限报警，限制值为："+highLimit + "； 实际值为："+dataValue );
            applicationContext.publishEvent(event);
        }
    }

    private void checkOverScopeLimitWarningResult(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        String highLimit = config.getLimitHighValue();
        String lowLimit = config.getLimitLowValue();
        String dataValue = payload.getDataValue();
        if(Double.compare(Double.parseDouble(dataValue), Double.parseDouble(highLimit))>0 && Double.compare(Double.parseDouble(dataValue), Double.parseDouble(lowLimit))<0){
            String dataType = payload.getDataType();
            BusinessDeviceWarnRecord event = createBusinessDeviceWarnRecord(config,payload);
            event.setWarningContent(dataType +"越限报警，限制值为："+lowLimit+ "-"+highLimit + "； 实际值为："+dataValue );
            applicationContext.publishEvent(event);
        }
    }

    /**
     * 创建设备报警记录 主要处理所有情况下的公共参数
     * @param config 报警设置
     * @param payload 上传数据
     * @return BusinessDeviceWarnRecord
     */
    private static BusinessDeviceWarnRecord createBusinessDeviceWarnRecord(BusinessDeviceUploadWarningConfig config, BusinessDeviceUploadData payload) {
        BusinessDeviceWarnRecord event = new BusinessDeviceWarnRecord();
        String checkType = config.getCheckType();
        event.setWarningLevel(config.getWarningLevel());
        event.setMeasureId(payload.getDeviceId());
        event.setDeviceData(payload.getDataValue());
        event.setTenantId(payload.getTenantId());
        event.setDeviceTime(payload.getDataTimestamp());
        event.setWarningCheckType(checkType);
        event.setDeviceDataType(config.getDataType());
        event.setRecordStatus("0");
        return event;
    }


    @Async("applicationMeasureEventTaskExecutor")
    @Override
    public void onApplicationEvent(BusinessDeviceUploadDataEvent eventSource) {
        try{
            log.debug("接收到设备数据");
            BusinessDeviceUploadData event = eventSource.getSource();
            log.debug("设备数据：{}",event);
            Long deviceId = event.getDeviceId();
//        Long tenantId = payload.getTenantId();
            List<BusinessDeviceUploadWarningConfig> list = service.getDeviceWarningConfig(String.valueOf(deviceId));
            for(BusinessDeviceUploadWarningConfig config : list) {
                checkWarningType(config,event);
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }

    }
}
